package com.qsw.qswcommonlib.util;

import java.util.Calendar;

/**
 * 字节相关操作工具类
 */
public class CommonByteUtil {

    /**
     * short转换为字节数组，低位在前
     *
     * @param value 数值
     * @return 转换后的2字节数组
     */
    public static byte[] shortToBytes(short value) {
        byte[] targets = new byte[2];
        targets[0] = (byte) (value & 0xFF);
        targets[1] = (byte) (value >> 8 & 0xFF);
        return targets;
    }

    /**
     * short转换为字节数组，高位在前
     *
     * @param value 数值
     * @return 转换后的2字节数组
     */
    public static byte[] shortToBytesHigh(short value) {
        byte[] targets = new byte[2];
        targets[0] = (byte) (value >> 8 & 0xFF);
        targets[1] = (byte) (value & 0xFF);
        return targets;
    }

    /**
     * int转换为字节数组，低位在前
     *
     * @param value 数值
     * @return 转换后的4字节数组
     */
    public static byte[] intToBytes(int value) {
        byte[] b = new byte[4];
        for (int i = 0; i < b.length; i++) {
            int offset = i * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * int转换为字节数组，高位在前
     *
     * @param value 数值
     * @return 转换后的4字节数组
     */
    public static byte[] intToBytesHigh(int value) {
        byte[] b = new byte[4];
        for (int i = 0; i < b.length; i++) {
            int offset = (b.length - 1 - i) * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * long转换为字节数组，低位在前
     *
     * @param value 数值
     * @return 转换后的8字节数组
     */
    public static byte[] longToBytes(long value) {
        byte[] b = new byte[8];
        for (int i = 0; i < b.length; i++) {
            int offset = i * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * long转换为字节数组，高位在前
     *
     * @param value 数值
     * @return 转换后的8字节数组
     */
    public static byte[] longToBytesHigh(long value) {
        byte[] b = new byte[8];
        for (int i = 0; i < b.length; i++) {
            int offset = (b.length - 1 - i) * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * long低4位转换为4字节数组，低位在前
     *
     * @param value 数值
     * @return 转换后的4字节数组
     */
    public static byte[] longToBytesHalf(long value) {
        byte[] b = new byte[4];
        for (int i = 0; i < b.length; i++) {
            int offset = i * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * long低4位转换为4字节数组，高位在前
     *
     * @param value 数值
     * @return 转换后的4字节数组
     */
    public static byte[] longToBytesHighHalf(long value) {
        byte[] b = new byte[4];
        for (int i = 0; i < b.length; i++) {
            int offset = (b.length - 1 - i) * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    /**
     * float转换为数组
     *
     * @param value 数值
     * @return 转换后的4字节数组
     */
    public static byte[] floatToBytes(float value) {
        return intToBytes(Float.floatToIntBits(value));
    }

    /**
     * 字节数组转换为short，低位在前
     *
     * @param b 2字节数组
     * @return 转换后的short
     */
    public static short bytesToShort(byte[] b) {
        return (short) (((b[1] << 8) & 0xFF00)
                | (b[0] & 0x00FF));
    }

    /**
     * 字节数组转换为short，高位在前
     *
     * @param b 2字节数组
     * @return 转换后的short
     */
    public static short bytesToShortHigh(byte[] b) {
        return (short) (((b[0] << 8) & 0xFF00)
                | (b[1] & 0x00FF));
    }

    /**
     * 字节数组转换为int，低位在前
     *
     * @param b 4字节数组
     * @return 转换后的int
     */
    public static int bytesToInt(byte[] b) {
        return ((b[3] << 24) & 0xFF000000)
                | ((b[2] << 16) & 0x00FF0000)
                | ((b[1] << 8) & 0x0000FF00)
                | (b[0] & 0x000000FF);
    }

    /**
     * 字节数组转换为int，高位在前
     *
     * @param b 4字节数组
     * @return 转换后的int
     */
    public static int bytesToIntHigh(byte[] b) {
        return ((b[0] << 24) & 0xFF000000)
                | ((b[1] << 16) & 0x00FF0000)
                | ((b[2] << 8) & 0x0000FF00)
                | (b[3] & 0x000000FF);
    }

    /**
     * 字节数组转换为float
     *
     * @param b 4字节数组
     * @return 转换后的float
     */
    public static float bytesTofloat(byte[] b) {
        return Float.intBitsToFloat(bytesToInt(b));
    }

    /**
     * 十进制数转换为BCD码
     *
     * @param decimal 十进制数
     * @return BCD码
     */
    public static int decimalToBCD(int decimal) {
        return decimal + (decimal / 10) * 6;
    }

    /**
     * BCD码转换为十进制数
     *
     * @param bcd BCD码
     * @return 十进制数
     */
    public static int bcdToDecimal(int bcd) {
        return bcd - (bcd >> 4) * 6;
    }

    /**
     * 获取日期时间的BCD码
     *
     * @param timestamp 时间戳
     * @return 结果，BCD[6]，格式YY-MM-DD-hh-mm-ss
     */
    public static byte[] getDateTimeBCD(long timestamp) {
        byte[] result = new byte[6];
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        result[0] = Byte.valueOf(String.valueOf(calendar.get(Calendar.YEAR)).substring(2, 4), 16);
        result[1] = Byte.valueOf(String.valueOf(calendar.get(Calendar.MONTH) + 1), 16);
        result[2] = Byte.valueOf(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)), 16);
        result[3] = Byte.valueOf(String.valueOf(calendar.get(Calendar.HOUR_OF_DAY)), 16);
        result[4] = Byte.valueOf(String.valueOf(calendar.get(Calendar.MINUTE)), 16);
        result[5] = Byte.valueOf(String.valueOf(calendar.get(Calendar.SECOND)), 16);
        return result;
    }

    /**
     * 将字节数组转换为大写十六进制字符串，不加前缀和间隔。
     * 每一个byte转换为两个十六进制数，比如一个byte将被转换为AB
     *
     * @param byteArray 字节数组
     * @return 转换后的大写十六进制字符串
     */
    public static String bytesToHex(byte[] byteArray) {
        return bytesToHex(byteArray, false, false, true);
    }

    /**
     * 将字节数组转换为大写十六进制字符串，通常用于Log测试，不加前缀加间隔。
     * 每一个byte转换为两个十六进制数，比如一个byte将被转换为AB
     *
     * @param byteArray  字节数组
     * @param byteLength 需要转换的数组长度
     * @return 转换后的大写十六进制字符串
     */
    public static String bytesToHexCommonPrint(byte[] byteArray, int byteLength) {
        return bytesToHex(byteArray, byteLength, false, true, true);
    }

    /**
     * 将字节数组转换为十六进制字符串。
     * 每一个byte转换为两个十六进制数，比如一个byte将被转换为AB或ab
     *
     * @param byteArray 字节数组
     * @param prefix    true：添加0x前缀；false：不添加前缀
     * @param interval  true：添加空格间隔；false：不添加间隔
     * @param upperCase true：大写；false：跟随源数据
     * @return 转换后的十六进制字符串
     */
    public static String bytesToHex(byte[] byteArray, boolean prefix, boolean interval, boolean upperCase) {
        return bytesToHex(byteArray, byteArray.length, prefix, interval, upperCase);
    }

    /**
     * 将字节数组转换为十六进制字符串。
     * 每一个byte转换为两个十六进制数，比如一个byte将被转换为AB或ab
     *
     * @param byteArray  字节数组
     * @param byteLength 需要转换的数组长度
     * @param prefix     true：添加0x前缀；false：不添加前缀
     * @param interval   true：天极爱空格间隔；false：不添加间隔
     * @param upperCase  true：大写；false：跟随源数据
     * @return 转换后的十六进制字符串
     */
    public static String bytesToHex(byte[] byteArray, int byteLength, boolean prefix, boolean interval, boolean upperCase) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < byteArray.length && i < byteLength; i++) {
            String s = Integer.toHexString(byteArray[i] & 0xFF);
            if (s.length() < 2) {
                s = "0" + s;
            }
            if (upperCase) {
                s = s.toUpperCase();
            }
            if (prefix) {
                s = "0x" + s;
            }
            if (interval) {
                s += " ";
            }
            sb.append(s);
        }
        return interval ? sb.substring(0, sb.length() - 1) : sb.toString();
    }

    /**
     * 十六进制字符串转换为字节数组
     *
     * @param hexStr 十六进制字符串
     * @return 转换后的字节数组
     */
    public static byte[] hexToBytes(String hexStr) {
        if (hexStr.length() % 2 != 0) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < result.length; i++) {
            char c1 = hexStr.charAt(i * 2);
            char c2 = hexStr.charAt(i * 2 + 1);
            result[i] = Short.valueOf(c1 + "" + c2, 16).byteValue();
        }
        return result;
    }

}
